﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using SharpMUD.Framework.Workflow.Generic;
using System.IO;
using SharpMUD.Application.BootStrap;
using SharpMUD.Framework.Services.Configuration;
using SharpMUD.Framework.IO;

namespace SharpMUD.Application
{
    public partial class MudServerApplication
        : IPulseDependent
    {
        protected static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(SharpMUD.Framework.ComponentModel.IService).Assembly, System.Reflection.MethodInfo.GetCurrentMethod().DeclaringType);

        #region Constructors
        public MudServerApplication()
            : this(new System.IO.FileInfo("mud.config"))
        {
            //DO NOTHING BECAUSE OF CONSTRUCTOR CHAINING
        }

        public MudServerApplication(System.IO.FileInfo configFile)
        {
            if (configFile == null)
                throw new ArgumentNullException("configFile");

            this.Initialize(PersistanceProxy<MudConfig>.XmlSerializationFile(configFile.FullName));
        }

        public MudServerApplication(MudConfig config)
        {
            if (config == null)
                throw new ArgumentNullException("config");

            this.Initialize(PersistanceProxy<MudConfig>.InMemory(config, false));
        }

        public MudServerApplication(PersistanceProxy<MudConfig> mudConfigurationPersistanceProxy)
        {
            if (mudConfigurationPersistanceProxy == null)
                throw new ArgumentNullException("mudConfigurationPersistanceProxy");

            this.Initialize(mudConfigurationPersistanceProxy);
        }
        #endregion

        private void Initialize(PersistanceProxy<MudConfig> mudConfigurationPersistanceProxy)
        {
            if (mudConfigurationPersistanceProxy == null)
                throw new ArgumentNullException("mudConfigurationPersistanceProxy");

            this.ExecutionStatus = ExecutionStatusTokens.Initializing;
            log.Info(this.ExecutionStatus.ToString());

            MudConfig config;
            try
            {
                config = mudConfigurationPersistanceProxy.Load();
            }
            catch (Exception e)
            {
                throw new MudConfigNotAvailableException(e);
            }
            this.AddService(config, true);

            var servicesToLoad =
                from ServiceConfigurationEntryBase sce in config.Services
                orderby ServiceDependencyAttribute.GetEffectiveDependencies(sce.ServiceTypeType).Count() ascending
                select sce;
            foreach (var i in servicesToLoad)
            {
                this.AddService(i,false);
            }
            foreach (var i in servicesToLoad)
            {
                this._LoadedServices.Where(s => i.ServiceTypeType.IsAssignableFrom(s.GetType())).ToList().ForEach(s => s.Initialize(this));
            }
            

            this.ExecutionStatus = ExecutionStatusTokens.Initialized;
            log.Info(this.ExecutionStatus.ToString());
        }

        #region IPulseDependent Members

        public void Pulse()
        {
            foreach (var service in this._LoadedServices.OfType<IPulseDependent>())
            {
                service.Pulse();
            }
        }

        #endregion
    }


}
